﻿Imports OpenTK
Imports OpenTK.Graphics.OpenGL4

Public Class ShadowmapBuilder
    Public texs() As Integer
    Public fbo As Integer
    Public rbo As Integer

    Private lightPosition As Vector3
    Private lightDireciton As Vector3
    Public Sub New(pos As Vector3, dir As Vector3, size As Integer)
        lightPosition = pos
        If dir <> Vector3.Zero Then
            texs = New Integer(1 - 1) {}
            texs(0) = GL.GenTexture()
            GL.BindTexture(TextureTarget.Texture2D, texs(0))
            GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.R32f, size, size, 0, PixelFormat.Red, PixelType.Float, IntPtr.Zero)
        Else
            texs = New Integer(6 - 1) {}
            GL.GenTextures(6, texs)
            GL.BindTexture(TextureTarget.Texture2D, texs(0))
            GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.R32f, size, size, 0, PixelFormat.Red, PixelType.Float, IntPtr.Zero)

            GL.BindTexture(TextureTarget.Texture2D, texs(1))
            GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.R32f, size, size, 0, PixelFormat.Red, PixelType.Float, IntPtr.Zero)

            GL.BindTexture(TextureTarget.Texture2D, texs(2))
            GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.R32f, size, size, 0, PixelFormat.Red, PixelType.Float, IntPtr.Zero)

            GL.BindTexture(TextureTarget.Texture2D, texs(3))
            GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.R32f, size, size, 0, PixelFormat.Red, PixelType.Float, IntPtr.Zero)

            GL.BindTexture(TextureTarget.Texture2D, texs(4))
            GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.R32f, size, size, 0, PixelFormat.Red, PixelType.Float, IntPtr.Zero)

            GL.BindTexture(TextureTarget.Texture2D, texs(5))
            GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.R32f, size, size, 0, PixelFormat.Red, PixelType.Float, IntPtr.Zero)
        End If

        fbo = GL.GenFramebuffer()
        rbo = GL.GenRenderbuffer()
        GL.RenderbufferStorage(RenderbufferTarget.Renderbuffer, RenderbufferStorage.DepthComponent32, size, size)
    End Sub

    Public Sub SetLightParameter()
        Dim program = ShaderManager.Active("ShadowMap")
        GL.UseProgram(program)
        Dim uLightPos As Integer = GL.GetUniformLocation(program, "LightPos")
        Dim uLightDir As Integer = GL.GetUniformLocation(program, "LightDir")

        GL.Uniform3(uLightPos, lightPosition.X, lightPosition.Y, lightPosition.Z)
        GL.Uniform3(uLightDir, lightDireciton.X, lightPosition.Y, lightPosition.Z)
    End Sub

    Public Sub Draw(df As DefferedRendering)
        Dim stride As Integer = df.triangleCount * 3 * 4 * 4
        GL.BindBuffer(BufferTarget.ArrayBuffer, RayTracing.sceneManager.bufferOutput)

        GL.EnableVertexAttribArray(0)
        GL.VertexAttribPointer(0, 4, VertexAttribPointerType.Float, False, 0, 0)
        GL.BindBuffer(BufferTarget.ElementArrayBuffer, df.ibo)
        GL.DrawElements(PrimitiveType.Triangles, df.triangleCount * 3, DrawElementsType.UnsignedShort, IntPtr.Zero)
    End Sub

    '要算一个场景的包围盒
    '点光源在包围盒内则渲染到天空盒
    '否则点光源或平行光源，渲染到平面
    Public Sub Render(df As DefferedRendering)
        GL.BindFramebuffer(FramebufferTarget.Framebuffer, fbo)
        GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, TextureTarget.Texture2D, texs(0), 0)
        GL.FramebufferRenderbuffer(FramebufferTarget.Framebuffer, FramebufferAttachment.DepthAttachment, RenderbufferTarget.Renderbuffer, rbo)

        GL.Clear(ClearBufferMask.ColorBufferBit Or ClearBufferMask.DepthBufferBit)
        GL.Enable(EnableCap.DepthTest)
        GL.ClearColor(0.5, 0.5, 0.5, 0.0)
        If lightDireciton <> Vector3.Zero Then

        Else

        End If
        GL.Flush()

        GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0)
    End Sub
End Class
